package com.pay.bean;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 微信扫码预支付结果。
 * 详情地址：https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2
 */
@Getter
@Setter
public class WxPayResult extends WxResult implements IPayResult, Serializable {

    private String openId;

    private String bankType;

    private BigDecimal totalFee;

    private BigDecimal cashFee;

    private String transactionId;

    private String outTradeNo;

    private Date timeEnd;

    //可选参数。
    private String attach;

    //交易类型
    private String tradeType = "NATIVE";

    @Override
    public  Map<Object, Object> initial(Map<String, String> params, String key) {
        Map<Object, Object> validParams = super.initial(params, key);
        try {
            if ("SUCCESS".equals(getReturnCode()) && "SUCCESS".equals(getResultCode()) && isSignValid()) {
                setTransactionId((String) validParams.get("transaction_id"));
                setOutTradeNo((String) validParams.get("out_trade_no"));
                setTradeType((String)validParams.get("trade_type"));
                setOpenId((String) validParams.get("openid"));
                setBankType((String) validParams.get("bank_type"));
                setAttach((String) validParams.get("attach"));
                if (validParams.get("total_fee") != null && validParams.get("total_fee").toString().length() > 0) {
                    setTotalFee(new BigDecimal((String) validParams.get("total_fee"))
                            .setScale(2, BigDecimal.ROUND_HALF_UP)
                            .divide(new BigDecimal(100)));
                }

                if (validParams.get("cash_fee") != null && validParams.get("cash_fee").toString().length() > 0) {
                    setCashFee(new BigDecimal((String) validParams.get("cash_fee"))
                            .setScale(2, BigDecimal.ROUND_HALF_UP)
                            .divide(new BigDecimal(100)));
                }

                if (validParams.get("time_end") != null && validParams.get("time_end").toString().length() > 0) {
                    setTimeEnd(new SimpleDateFormat("yyyyMMddHHmmss").parse((String) validParams.get("time_end")));
                }

            }
        } catch (Exception ex) {
        }
        return validParams;
    }

    public String getResponse() {
        String result = "<xml>\n" +
                "  <return_code><![CDATA[%s]]></return_code>\n" +
                "  <return_msg><![CDATA[%s]]></return_msg>\n" +
                "</xml>";

        if ("SUCCESS".equals(getReturnCode()) && isSignValid()) {
            result = String.format(result, "SUCCESS", "OK");
        }else{
            result = String.format(result, "FAIL", "ERROR");
        }
        return result;
    }

    @Override
    public String getTradeNo() {
        return getTransactionId();
    }

    @Override
    public String getPayMode() {
        return PayMode.WX_PAY.name();
    }

    @Override
    public String getTradeStatus() {
        return getResultCode();
    }

    @Override
    public String getSellerId() {
        return getMchId();
    }

    @Override
    public String getBuyerId() {
        return getOpenId();
    }

    @Override
    public BigDecimal getPaidAmount() {
        return getTotalFee();
    }

    @Override
    public Date getPayTime() {
        return getTimeEnd();
    }

    @Override
    public boolean isPaid() {
        return "SUCCESS".equals(getReturnCode()) && "SUCCESS".equals(getResultCode()) && isSignValid();
    }

    @Override
    public boolean isQueryResult() {
        return false;
    }

    @Override
    public TradeState getStandardTradeStatus() {
        TradeState state = null;
        if (isQueryResult()) {
            switch (getTradeStatus()) {
                case "SUCCESS":
                    state = TradeState.TRADE_SUCCESS;
                    break;
                case "REFUND":
                case "NOTPAY":
                case "CLOSED":
                case "REVOKED":
                case "PAYERROR":
                    state = TradeState.TRADE_FAIL;
                    break;
                case "USERPAYING":
                    state = TradeState.PAYING;
                    break;
            }
        }else{
            state = isPaid() ? TradeState.TRADE_SUCCESS : TradeState.TRADE_FAIL;
        }
        return state;
    }
}
